package com.sbox.album.model;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import com.sbox.util.AlbumConst;
import com.sbox.util.AlbumLog;
import com.sbox.util.Utils;

import android.os.Environment;

public class AlbumManager {
	private AlbumInfo[] mAlbums = null;
	
	private static AlbumManager sAlbumManager = null;
	
	public static AlbumManager getInstance() {
		if( sAlbumManager == null ) {
			sAlbumManager = new AlbumManager();
		}		
		return sAlbumManager;
	}
	
	private AlbumManager()
	{
		mAlbums = listAlbums();
	}
	
	public int getAlbumCount() {
		if( mAlbums == null )
			return 0;
		return mAlbums.length;
	}
	
	public AlbumInfo getAlbum(int index) {
		if( index < 0 || index >= getAlbumCount() )
			return null;
		
		return mAlbums[index];
	}
	
	public void createAlbum(String name) {
		File f = null;
		if( name.startsWith( AlbumConst.ALBUM_ROOT_PATH ) ) {
			f = new File(name);			
		}
		else {
			f = new File( AlbumConst.ALBUM_ROOT_PATH + "/" + name);
		}
		
		if( f.exists() )
			return;
		
		f.mkdirs();
		
	}
	
	public boolean findAlbum(String name)
	{
		File f = null;
		if( name.startsWith( AlbumConst.ALBUM_ROOT_PATH ) ) {
			f = new File(name);			
		}
		else {
			f = new File( AlbumConst.ALBUM_ROOT_PATH + "/" + name);
		}
		
		if( f.exists() )
			return true;
		
		return false;
	}
	
	public static AlbumInfo[] listAlbums()
	{
		File root = null;
		int count = 0;
		File[] dirs = null;
		AlbumInfo[] albums = null;
		
		AlbumLog.info("listAlbums, enter");
		
		String sdState = Environment.getExternalStorageState();		
		if( !sdState.equals(Environment.MEDIA_MOUNTED) && !sdState.equals(Environment.MEDIA_MOUNTED_READ_ONLY) )
		{
			AlbumLog.info("listAlbums, sdcard is not ready, state = " + sdState);
			return null;
		}
		
		root = new File(AlbumConst.ALBUM_ROOT_PATH);
		if( !root.exists() )
		{
			AlbumLog.info("listAlbums, root dir doesnt exist.");
			root.mkdirs();
			return null;
		}
		
		dirs = root.listFiles(mDirFilter);
		count  = dirs.length;
		if( count == 0 )
			return null;
		
		albums = new AlbumInfo[count];		
		for( int i=0; i<count; i++ )
		{
			albums[i] = new AlbumInfo(dirs[i].getAbsolutePath());			
		}	
		Arrays.sort(albums, 0, count, new AlbumComparator());
		
		return albums;
	}
	
	
	
	public static PictureInfo[] listPicturesInSystem()
	{
		return listPictures(AlbumConst.SYSTEM_IMAGE_PATH);
	}
	
	public static PictureInfo[] listPictures(String folder)
	{
		File sdPicRoot = null;
		int count = 0;
		File[] files = null;
		PictureInfo[] pics = null;
		
		String sdState = Environment.getExternalStorageState();		
		if( !sdState.equals(Environment.MEDIA_MOUNTED) && !sdState.equals(Environment.MEDIA_MOUNTED_READ_ONLY ) )
			return null;
		
		sdPicRoot = new File(folder);
		
		files = sdPicRoot.listFiles(mFileFilter);
		if( files == null || files.length == 0 )
			return null;
		
		count = files.length;
		pics = new PictureInfo[count];
		for( int i=0; i<count; i++ )
		{
			pics[i] = new PictureInfo( files[i].getAbsolutePath() );
		}
		Arrays.sort(pics, 0, count, new PictureComparator());
		
		return pics;
	}

	@SuppressWarnings("unchecked")	
	public static long[] listPictureDates(String folder) {
		int count = 0;
		long tmpTime = 0;
		PictureInfo[] pics = listPictures(folder);
		ArrayList<Long> dates = new ArrayList<Long>();
		long[] ldates = null;
		
		if( pics == null )
			return null;
		
		count = pics.length;
		for( int i=0; i<count; i++ ) {
			tmpTime =pics[i].getTime();
			
			if( !dates.contains(tmpTime) )
				dates.add(tmpTime);
		}
		
		count = dates.size();
		if( count == 0 )
			return null;
		ldates = new long[dates.size()];
		for( int i=0; i<count; i++ ) {
			ldates[i] = dates.get(i);
		}

		return ldates;
	}
	
	public static DateAlbumInfo[] listAlbumByDate(String folder) {
		int count = 0;
		long tmpTime = 0;
		boolean find = false;
		PictureInfo[] pics = listPictures(folder);
		ArrayList<DateAlbumInfo> dates = new ArrayList<DateAlbumInfo>();
		
		if( pics == null )
			return null;
		
		count = pics.length;
		for( int i=0; i<count; i++ ) {
			tmpTime = Utils.getDayOfDate(pics[i].getTime() );
			find = false;
			
			for( int j=dates.size()-1; j>=0; j-- ) {
				if( tmpTime == dates.get(j).getDate() ) {
					dates.get(j).addPicture(pics[i]);
					find = true;
					break;
				}
			}
			
			if( !find ) {
				DateAlbumInfo newAlbum = new DateAlbumInfo(tmpTime);
				newAlbum.addPicture(pics[i]);
				dates.add(newAlbum);
			}
		}

		return dates.toArray( new DateAlbumInfo[dates.size()] );
	}
	
	public static void importPictures(PictureInfo[] pics, AlbumInfo album) {
		if( pics == null || pics.length == 0 || album == null )
			return;
		
		for( PictureInfo pic: pics ) {
			importPicture(pic, album);
		}
	}
	
	public static void importPicture(PictureInfo pic, AlbumInfo album) {
		String fileName = pic.getFileName();
		String destFileName = null;
		String albumName = null;
		
		albumName = pic.getAlbumName();
		if( albumName == null ) {
			AlbumLog.error("pic.getAlbumName return null, picture=" + pic.getFileName());
			return;
		}
		if( fileName.startsWith(AlbumConst.ALBUM_ROOT_PATH) ) {			
			destFileName = AlbumConst.ALBUM_ROOT_PATH + album.getName() + "/" + pic.getName();			
		} else if( fileName.startsWith(AlbumConst.SYSTEM_IMAGE_PATH) ) {
			destFileName = AlbumConst.ALBUM_ROOT_PATH + album.getName() + "/" + pic.getName();
		}
		
		AlbumLog.info("moveFile, fileName=" + fileName + ", destFileName=" + destFileName);
		Utils.moveFile(fileName, destFileName);
	}
			
	private static FileFilter mDirFilter = new FileFilter()
	{
		@Override
		public boolean accept(File pathname)
		{
			if( pathname.isHidden() )
				return false;
			if( !pathname.isDirectory() )
				return false;
			else
				return true;
			
		}
	};

	private static FileFilter mFileFilter = new FileFilter()
	{
		@Override
		public boolean accept(File pathname)
		{
			if( !pathname.isDirectory() )
				return true;
			else
				return false;
			
		}
	};
	
	public static class AlbumComparator implements Comparator<AlbumInfo> {

		@Override
		public int compare(AlbumInfo object1,
				AlbumInfo object2) {
			return object1.getPath().compareToIgnoreCase(object2.getPath());
		}
		
	}
	
	public static class PictureComparator implements Comparator<PictureInfo> {

		@Override
		public int compare(PictureInfo object1,
				PictureInfo object2) {
			return object1.getFileName().compareToIgnoreCase(object2.getFileName());
		}
		
	}
}
